<template>
  <div>
    <div :class="$style.channelInput" @click="onOpen" :style="customStyles">
      <div v-if="loading" v-loading="loading" style="margin: 18px 0 0 0"></div>
      <span v-else>{{ checkedSize }}个选中项</span>
    </div>
    <el-dialog
      title="选择渠道"
      :visible="channelDialog"
      width="43%"
      @close="onClose"
      :modal="modal"
      :close-on-click-modal="false"
      :modal-append-to-body="modalAppendToBody"
      :append-to-body="appendToBody"
    >
      <div>
        <div :class="$style.channelFilter">
          <div style="width: 80%">
            <input placeholder="输入关键字" v-model="filterText" clearable :class="$style.channelInput2" @blur="filterTextBlur" />
          </div>
          <div>
            <el-upload
              ref="upload"
              class="upload-demo"
              action="https://jsonplaceholder.typicode.com/posts/"
              :limit="1"
              :auto-upload="false"
              :before-upload="onBeforeUpload"
              :on-change="onChange"
              :on-error="onError"
              :show-file-list="true"
              accept=".xlsx"
            >
              <div>
                <el-button size="medium" :class="$style.channelUploadButton">点击上传</el-button>
              </div>
            </el-upload>
          </div>
        </div>
        <div :class="$style.channelTree">
          <el-tree
            class="filter-tree"
            :data="channelTreeData"
            node-key="id"
            v-loading="treeLoading"
            :props="defaultProps"
            show-checkbox
            :filter-node-method="filterNode"
            ref="tree"
          >
          </el-tree>
        </div>
      </div>
      <div slot="footer" :class="$style.blackDialogFooter">
        <el-button type="success" @click="refresh" plain size="medium">刷新</el-button>
        <el-button type="primary" @click="clearTree" plain size="medium">清空重置</el-button>
        <el-button type="success" @click="affirm()" plain size="medium">确认</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { Notification } from 'element-ui';
import XLSX from 'xlsx';
import { TOP_CHANNELS } from '@/constants';
import { loadChannel } from './api';

export default {
  name: 'channel-tree',
  props: {
    topChannelCode: {
      type: String,
      default: '',
    },
    channels: {
      type: Array,
      default: () => [],
    },
    checkedSize: {
      type: Number,
      default: () => 0,
    },
    inputWidth: {
      type: Number,
      default: () => 50,
    },
    modal: {
      type: Boolean,
      default: () => true,
    },
    modalAppendToBody: {
      type: Boolean,
      default: () => true,
    },
    appendToBody: {
      type: Boolean,
      default: () => false,
    },
    customStyle: {
      // 自定义样式
      type: Object,
      default: () => {},
      required: false,
    },
  },
  watch: {
    // topChannelCode(topChannelCode) {
    //   console.log('渠道树：', topChannelCode);
    //   if (!topChannelCode) {
    //     return;
    //   }
    //   this.initChannelTree(topChannelCode);
    // },
  },
  data() {
    return {
      treeLoading: false,
      loading: false,
      channelDialog: false,
      defaultProps: {
        children: 'children',
        label: 'label',
      },
      filterText: '',
      channelTreeData: [],
    };
  },
  computed: {
    customStyles() {
      return {
        ...this.customStyle,
        width: this.inputWidth + '%',
      };
    },
  },
  methods: {
    //刷新渠道
    refresh() {
      this.listAvailable(this.topChannelCode);
    },
    //清空树
    clearTree() {
      this.$refs.tree.setCheckedKeys([]);
    },
    //确认
    affirm() {
      const nodes = this.$refs.tree.getCheckedNodes(true, false);
      this.channelDialog = false;
      this.$emit('affirm', nodes);
    },
    //查询渠道
    async listAvailable(topChannelCode) {
      try {
        this.treeLoading = true;
        this.channelTreeData = [];
        const result = await loadChannel(topChannelCode);
        const channelData = {
          id: topChannelCode,
          label: TOP_CHANNELS.find(i => i.id === topChannelCode)?.name,
          children: [],
        };
        this.createTreeData(channelData, result);
        this.channelTreeData.push(channelData);
        //渠道信息缓存
        localStorage[topChannelCode + '-TREE'] = JSON.stringify(this.channelTreeData);
        this.treeLoading = false;
      } catch (error) {
        console.log(error);
        this.treeLoading = false;
      }
    },
    //组装渠道树
    createTreeData(topChannelData, allChannels) {
      const channelCode = topChannelData.id;
      const childrenArray = [];
      allChannels.forEach(item => {
        if (item.parentCode === channelCode) {
          const childrenChannel = {};
          childrenChannel.id = item.channelCode;
          childrenChannel.label = item.name;
          childrenArray.push(childrenChannel);
        }
      });
      topChannelData.children = childrenArray;
      if (childrenArray.length > 0) {
        childrenArray.forEach(item => {
          this.createTreeData(item, allChannels);
        });
      }
    },
    initChannelTree(topChannelCode) {
      //获取渠道树缓存
      const cacheChannel = localStorage[topChannelCode + '-TREE'];
      if (cacheChannel) {
        this.channelTreeData = JSON.parse(cacheChannel);
      } else {
        this.listAvailable(topChannelCode);
      }
    },
    async onOpen() {
      if (!this.topChannelCode) {
        this.channelDialog = false;
        Notification({
          title: '提示',
          message: '请选择顶级渠道',
          type: 'warning',
        });
        return;
      }
      this.loading = true;
      await this.initChannelTree(this.topChannelCode);
      this.channelDialog = true;
      this.filterText = '';
      if (this.$refs.tree && this.channels && this.channels.length === 0) {
        this.$refs.tree.setCheckedKeys([]);
      } else {
        const channelCodes = [];
        this.channels.forEach(channel => {
          channelCodes.push(channel.id);
        });
        //dom加载完毕后执行
        this.$nextTick(function() {
          //这里写方法
          this.$refs.tree?.setCheckedKeys(channelCodes);
        });
      }
      this.loading = false;
    },
    onClose() {
      this.channelDialog = false;
      this.$refs.upload.uploadFiles = [];
    },
    onError(err) {
      console.log('err:', err);
      Notification({
        title: '错误',
        message: '文件上传失败',
        type: 'error',
      });
    },
    onBeforeUpload(file) {
      console.log('onBeforeUpload:', file);
    },
    onChange(file) {
      const reader = new FileReader();
      reader.onload = e => {
        let data = e.target.result;
        const workbook = XLSX.read(data, { type: 'buffer' });
        const [sheetName] = workbook.SheetNames;
        const sheetInfo = workbook.Sheets[sheetName];
        if (sheetInfo.A1.v !== '渠道编码') {
          Notification({
            title: '错误',
            message: '模板格式错误',
            type: 'error',
          });
          return;
        }
        const parsedSheetInfo = XLSX.utils.sheet_to_json(sheetInfo);
        const channels = parsedSheetInfo.map(item => ({
          channelCode: String(item['渠道编码'] || ''),
        }));
        const channelCodes = [];
        channels.forEach(channelCode => {
          channelCodes.push(channelCode.channelCode);
        });
        this.$refs.tree.setCheckedKeys(channelCodes);
        Notification({
          title: '提示',
          message: '文件上传成功',
          type: 'success',
        });
      };
      reader.readAsArrayBuffer(file.raw);
    },
    filterNode(value, data) {
      if (!value) return true;
      return data.id === value || data.label.indexOf(value) !== -1 || data.id.indexOf(value) !== -1;
    },
    filterTextBlur() {
      this.$refs.tree.filter(this.filterText);
    },
  },
};
</script>

<style lang="scss" module>
.channelInput {
  -webkit-appearance: none;
  background-color: #e0e0e0;
  background-image: none;
  border-radius: 4px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  color: #404040;
  display: inline-block;
  font-size: inherit;
  height: 40px;
  line-height: 40px;
  outline: none;
  padding: 0 15px;
  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
  cursor: pointer;
}
.channelUploadButton {
  margin-left: 10px;
}
.blackDialogFooter {
  text-align: center;
}
.channelTree {
  height: 400px;
  overflow: hidden;
  overflow-y: scroll;
  margin: 30px 0 0 30px;
}
.channelFilter {
  display: flex;
  margin-left: 20px;
}

.channelInput2 {
  -webkit-appearance: none;
  background-image: none;
  border-radius: 4px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  color: #404040;
  display: inline-block;
  font-size: inherit;
  height: 35.6px;
  line-height: 35.6px;
  outline: none;
  padding: 0 15px;
  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
  cursor: pointer;
  width: 95%;
}
</style>
